<?php

namespace Frieza\Modules\AdServing\Controllers;

use App\Admin\Extensions\WorkContent;
use App\Http\Controllers\Controller;
use App\Pockets\GridDataModel as pGridDataModel;
use Doraemon\model\AdServing\AgentCompany;
use Doraemon\model\AdServing\Channel;
use Doraemon\model\AdServing\Serving;
use Doraemon\model\AdServing\ServingData;
use Doraemon\pockets\excel\DownExcel;
use Doraemon\pockets\excel\ReadExcel;
use Doraemon\service\AdServing\AgentCompanyService;
use Doraemon\service\AdServing\ChannelService;
use Doraemon\service\AdServing\ServingDataService;
use Doraemon\tools\Log;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Encore\Admin\Widgets\Form;
use Encore\Admin\Widgets\Tab;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\MessageBag;

class AdServingDataController extends Controller
{
    const PAGE_SIZE = 50;

    const rules = [
        'day' => 'required',
        'channel_one_name' => 'required',
        'channel_one_code' => 'required',
        'channel_two_name' => 'required',
        'channel_two_code' => 'required',
        'channel_three_name' => 'required',
        'channel_three_code' => 'required',
        'agent_name' => 'required',
        'agent_code' => 'required',
        'terminal' => 'required',
        'cost' => 'required|numeric',
        'expose' => 'required|integer',
        'click' => 'required|integer',
        'download' => 'required|integer',
    ];

    const message = [
        'required' => '参数 :attribute是必须传递参数.',
        'max' => '参数 :attribute 不能大于 :max.',
        'integer' => '参数 :attribute是必须是整型'
    ];

    /**
     * @param Request $request
     * @param Content $content
     * @return Content
     */
    public function getList(Request $request, Content $content): Content
    {
        $export_url = $request->getQueryString();

        $params = $request->all();
        $listAndTotal = ServingDataService::getFilterData($params);
//        Log::debug('投放数据列表', $listAndTotal);
        $gridModel = new pGridDataModel($listAndTotal['list'], $listAndTotal['total'], [
            'perPage' => self::PAGE_SIZE,
        ]);

        $listGrid = Admin::grid($gridModel, function (Grid $grid) use ($gridModel, $export_url) {
            $grid->paginate($gridModel->getPerPage());

            $grid->tools(function ($tools) use ($export_url) {
                $tools->append(<<<HTML
<a class="btn button-success" href="javascript:layer.open({type: 2,title: '导入',maxmin: true,area: ['400px', '650px'],content: '/admin/adServing/serving-data/file-import'});">
    <i class="fa fa-upload"/> 导入
</a>
HTML
);

                $tools->append(<<<HTML
<a class="btn button-success" href="/admin/adServing/serving-data/file-export?{$export_url}">
    <i class="fa fa-download"/> 导出
</a>
HTML
                );

                $tools->append(<<<HTML
<a class='btn button-success' href='/admin/adServing/serving-data/down-excel'>
    <i class='fa fa-file-excel-o'/> 导出模板
</a>
HTML
                );
            });

            $grid->filter(function (Grid\Filter $filter) {
                $filter->disableIdFilter();

                $channelsOneOptions = [];
                $channelsTwoOptions = [];
                $channelsThreeOptions = [];
                $channels = (array)Channel::select('*');
                foreach ($channels as $channel) {
                    if ($channel['level'] == 1) {
                        $channelsOneOptions[$channel['id']] = $channel['name'];
                    } elseif ($channel['level'] == 2) {
                        $channelsTwoOptions[$channel['id']] = $channel['name'];
                    } elseif ($channel['level'] == 3) {
                        $channelsTwoOptions[$channel['id']] = $channel['name'];
                    }
                }

                $filter->column(1 / 3, function (Grid\Filter $filter) use ($channelsOneOptions) {
                    $filter->equal('c1_id', '投放大类')
                        ->select($channelsOneOptions)
                        ->load('c2_id', '/admin/adServing/serving/options/');


                    $filter->equal('day', '日期')->date();
                });
                $filter->column(1 / 3, function (Grid\Filter $filter) use ($channelsTwoOptions) {
                    $filter->equal('c2_id', '投放渠道')
                        ->select($channelsTwoOptions)
                        ->load('c3_id', '/admin/adServing/serving/options/');
                });
                $filter->column(1 / 3, function (Grid\Filter $filter) use ($channelsThreeOptions) {
                    $filter->equal('c3_id', '投放位置')->select($channelsThreeOptions);
                });


                $filter->expand();
            });

            $grid->disableExport();
            $grid->disableRowSelector();

            $grid->column('day', '日期');
            $grid->column('c1_id', '投放大类')->display(function () {
                return $this['channelOne']['name'];
            });
            $grid->column('c2_id', '投放渠道')->display(function () {
                return $this['channelTwo']['name'];
            });
            $grid->column('c3_id', '投放位置')->display(function () {
                return $this['channelThree']['name'];
            });
            $grid->column('ac_id', '代理商')->display(function () {
                return $this['company']['name'];
            });
            $grid->column('terminal', '端')->using([1 => "ios", 2 => "android"]);

            $grid->column('cost', '消耗')->display(function () {
                return sprintf('%.2f', $this['cost'] / 100.0);
            });
            $grid->column('expose', '曝光');
            $grid->column('click', '点击');
            $grid->column('download', '下载');

            $grid->column('addtime', '创建时间')->display(function () {
                return $this->addtime ? date('Y-m-d H:i:s', $this->addtime) : 0;
            });
            $grid->column('edittime', '更新时间')->display(function () {
                return $this->edittime ? date('Y-m-d H:i:s', $this->edittime) : 0;
            });
        });

        return $content
            ->header('渠道消耗数据管理')
            ->breadcrumb(
                [
                    'text' => '渠道消耗数据管理',
                    'url' => '/adServing/serving-data'
                ],
            )
            ->body($listGrid);
    }


    public function edit(Content $content, int $id = 0): Content
    {
        if ($id > 0) {
            $title = '编辑渠道消耗';
            $data = ServingData::get('*', ['id' => $id]);
            $data['cost'] = $data['cost'] / 100.0;

            $form = new Form($data);
            $form->hidden('id');
        } else {
            $title = '创建渠道消耗';
            $form = new Form();
        }

        $form->date('day', '日期')
            ->required()
            ->format('YYYY-MM-DD');

        $form->select('c1_id', '投放大类')
            ->required()
            ->options(ChannelService::getChannelSelectOptionsByLevel(1))
            ->load('c2_id', '/admin/adServing/serving/options/');

        $form->select('c2_id', '投放渠道')
            ->required()
            ->options(ChannelService::getChannelSelectOptionsByLevel(2))
            ->load('c3_id', '/admin/adServing/serving/options/');

        $form->select('c3_id', '投放位置')
            ->required()
            ->options(ChannelService::getChannelSelectOptionsByLevel(3));

        $form->select('ac_id', '代理商')
            ->required()
            ->options(AgentCompanyService::getAllForSelectOptions());

        $form->select('terminal', '端')
            ->required()
            ->options([1 => 'ios', 2 => 'android']);

        $form->number('cost', '消耗')->default(0);
        $form->number('click', '点击')->default(0);

        $form->number('expose', '曝光')->default(0);
        $form->number('download', '下载')->default(0);

        $form->action('/admin/adServing/serving-data/save');

        $tab = new Tab();
        $tab->add("$title", $form);
        return $content
            ->header('渠道消耗数据管理')
            ->breadcrumb(
                [
                    'text' => '渠道消耗数据管理',
                    'url' => '/adServing/serving-data',
                ],
                [
                    'text' => "$title",
                ]
            )
            ->body($tab);
    }


    public function save(Request $request)
    {
        $params = $request->all();
        $rs = ServingDataService::addData($params);
        if ($rs === true) {
            $success = new MessageBag([
                'title' => '保存成功'
            ]);
            return redirect('/admin/adServing/serving-data')->with(compact('success'));
        } else {
            $error = new MessageBag([
                'title' => '保存失败,' . $rs,
            ]);
            return back()->with(compact('error'));
        }
    }

    public function exportData(Request $request)
    {
        $downExcel = new DownExcel();
        $title = "渠道投放消耗数据";
        $downExcel->setFrontBold('1');
        $downExcel->setFileName($title);
        $downExcel->setTitle($title);
        $downExcel->setSheetTitle($title);
        $widths = [
            'A' => 10,
            'B' => 15,
            'C' => 25,
            'D' => 15,
            'E' => 25,
            'F' => 15,
            'G' => 25,
            'H' => 10,
            'I' => 25,
            'J' => 10,
            'K' => 10,
            'L' => 10,
            'M' => 10,
            'N' => 10,
        ];
        $downExcel->setWidth($widths);
        $head = [
            '日期',
            '渠道大类',
            '渠道大类（英文简称）',
            '投放渠道',
            '投放渠道（英文简称）',
            '投放位置',
            '投放位置（英文简称）',
            '代理商',
            '代理商（英文简称）',
            'app端',
            '消耗',
            '曝光',
            '点击',
            '下载',
        ];

        $rowArr = Channel::select(['id', 'code', 'name']);
        $channelArrById = [];
        foreach ($rowArr as $row) {
            $channelArrById[$row['id']] = $row;
        }

        $rowArr = AgentCompany::select(['id', 'code', 'name']);
        $companyArrById = [];
        foreach ($rowArr as $row) {
            $companyArrById[$row['id']] = $row;
        }

        $data = [];

        $params = $request->all();
        $params['nopage'] = true;
        $listAndTotal = ServingDataService::getFilterData($params);
        foreach ($listAndTotal['list'] as $row) {
            $data[] = [
                $row['day'],
                $channelArrById[$row['c1_id']]['name'],
                $channelArrById[$row['c1_id']]['code'],
                $channelArrById[$row['c2_id']]['name'],
                $channelArrById[$row['c2_id']]['code'],
                $channelArrById[$row['c3_id']]['name'],
                $channelArrById[$row['c3_id']]['code'],
                $companyArrById[$row['ac_id']]['name'],
                $companyArrById[$row['ac_id']]['code'],
                [1 => 'ios', 2 => 'android'][$row['terminal']],
                sprintf('%.2f', $row['cost'] / 100.0),
                $row['expose'],
                $row['click'],
                $row['download'],
            ];
        }

        $downExcel->create($data, $head);
        return back();
    }


    /**
     * 导出Excel模板
     * @return \Illuminate\Http\RedirectResponse
     */
    public function downExcel()
    {
        $yesterday = date('Ymd', strtotime('-1 days'));

        $downExcel = new DownExcel();
        $title = "渠道消耗模板{$yesterday}";
        $downExcel->setFrontBold('1');
        $downExcel->setFileName($title);
        $downExcel->setTitle($title);
        $downExcel->setSheetTitle($title);
        $widths = [
            'A' => 10,
            'B' => 15,
            'C' => 25,
            'D' => 15,
            'E' => 25,
            'F' => 15,
            'G' => 25,
            'H' => 10,
            'I' => 25,
            'J' => 10,
            'K' => 10,
            'L' => 10,
            'M' => 10,
            'N' => 10,
        ];
        $downExcel->setWidth($widths);
        $head = [
            '日期',
            '渠道大类',
            '渠道大类（英文简称）',
            '投放渠道',
            '投放渠道（英文简称）',
            '投放位置',
            '投放位置（英文简称）',
            '代理商',
            '代理商（英文简称）',
            'app端',
            '消耗',
            '曝光',
            '点击',
            '下载',
        ];

        $rowArr = Channel::select(['id', 'code', 'name']);
        $channelArrById = [];
        foreach ($rowArr as $row) {
            $channelArrById[$row['id']] = $row;
        }

        $rowArr = AgentCompany::select(['id', 'code', 'name']);
        $companyArrById = [];
        foreach ($rowArr as $row) {
            $companyArrById[$row['id']] = $row;
        }

        $data = [];

        Log::debug('导出模板数据', [Admin::user()->id]);
        $rowArr = Serving::select('*', [
            'admin_uid' => Admin::user()->id,
            'status' => 1,
            'ORDER' => [
                'id' => 'DESC',
            ],
        ]);
        $uniqKeyArr = [];
        foreach ($rowArr as $row) {
            $key = $row['channel_one_id'] . '-' . $row['channel_two_id'] . '-' . $row['channel_three_id'] . '-' . $row['agent_company_id'] . '-' . $row['terminal'];
            if (!in_array($key, $uniqKeyArr)) {
                $uniqKeyArr[] = $key;

                $data[] = [
                    $yesterday,
                    $channelArrById[$row['channel_one_id']]['name'],
                    $channelArrById[$row['channel_one_id']]['code'],
                    $channelArrById[$row['channel_two_id']]['name'],
                    $channelArrById[$row['channel_two_id']]['code'],
                    $channelArrById[$row['channel_three_id']]['name'],
                    $channelArrById[$row['channel_three_id']]['code'],
                    $companyArrById[$row['agent_company_id']]['name'],
                    $companyArrById[$row['agent_company_id']]['code'],
                    [1 => 'ios', 2 => 'android'][$row['terminal']],
                    0,
                    0,
                    0,
                    0,
                ];
            }
        }
        $downExcel->create($data, $head);
        return back();
    }

    /**
     * 返回导入excel文件的表单
     * @param WorkContent $content
     * @return WorkContent
     */
    public function importExcel(WorkContent $content)
    {
        $form = new Form();
        $form->file('excel', '上传Excel')->required()->removable()->help('请严格按照模板格式');
        $form->action('/admin/adServing/serving-data/save-excel');
        return $content->body($form);
    }


    /**
     * 保存Excel数据
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse|string
     * @throws \Exception
     */
    public function saveExcel(Request $request)
    {
        $params = $request->all();
        $newFile = 'adServing-' . date('YmdHis') . '.xls';
        $newFilePath = '/tmp' . '/' . $newFile;
        $rs = move_uploaded_file($params['excel'], $newFilePath);
        if (!$rs) {
            $error = new MessageBag([
                'title' => '文件保存失败',
            ]);
            return back()->with(compact('error'));
        }
        $excel = new ReadExcel($newFile);
        try {
            $excelRawData = $excel->getExcelDataNoHeader($newFilePath);
        } catch (\PHPExcel_Reader_Exception $exception) {
            $error = new MessageBag([
                'title' => 'Excel文件读取失败，只支持xls格式',
            ]);
            return back()->with(compact('error'));
        }

        Log::debug('Excel原始数据', $excelRawData);

        $excelData = [];
        foreach ($excelRawData as $row) {
            if (is_null($row[0])) {
                break;
            }
            $excelData[] = $row;
        }

        $excelRows = [];
        //检查 格式化
        $iMax = count($excelData);
        for ($i = 1; $i < $iMax; $i++) {
            $singleData = array_combine(array_keys(self::rules), $excelData[$i]);

            //筛查 有一条不符合直接返回
            $validator = Validator::make($singleData, self::rules, self::message);
            if ($validator->fails()) {
                return $validator->errors()->first();
            }

            $excelRows[] = $singleData;
        }

        //准备其他相关数据
        $rowArr = Channel::select(['id', 'code', 'name']);
        $channelArrByCode = [];
        foreach ($rowArr as $row) {
            $channelArrByCode[$row['code']] = $row;
        }
        $rowArr = AgentCompany::select(['id', 'code', 'name']);
        $companyArrByCode = [];
        foreach ($rowArr as $row) {
            $companyArrByCode[$row['code']] = $row;
        }


        //去除重复数据
        $removeDupRows = [];
        foreach ($excelRows as $row) {
            $uniqKey = $row['day'] . '-' . $row['channel_one_code'] . '-' . $row['channel_two_code'] . '-' . $row['channel_three_code'] . '-' . $row['agent_code'] . '-' . $row['terminal'];
            $removeDupRows[$uniqKey] = $row;
        }
        Log::debug('Excel数据', $removeDupRows);

        //导入数据
        $timestamp = time();
        foreach ($removeDupRows as $row) {
            $existId = ServingData::get('id', [
                'c1_id' => $channelArrByCode[$row['channel_one_code']]['id'],
                'c2_id' => $channelArrByCode[$row['channel_two_code']]['id'],
                'c3_id' => $channelArrByCode[$row['channel_three_code']]['id'],
                'day' => $row['day'],
                'ac_id' => $companyArrByCode[$row['agent_code']]['id'],
                'terminal' => ['ios' => 1, 'android' => 2][$row['terminal']],
            ]);
            if (!empty($existId)) {
                //编辑
                Log::debug('编辑投放数据', [$existId]);
                ServingData::update(
                    [
                        'cost' => $row['cost'] * 100,
                        'expose' => $row['expose'],
                        'click' => $row['click'],
                        'download' => $row['download'],
                        'edittime' => $timestamp,
                    ],
                    ['id' => $existId]
                );
            } else {
                //插入
                ServingData::insert([
                        'day' => $row['day'],
                        'c1_id' => $channelArrByCode[$row['channel_one_code']]['id'],
                        'c2_id' => $channelArrByCode[$row['channel_two_code']]['id'],
                        'c3_id' => $channelArrByCode[$row['channel_three_code']]['id'],
                        'ac_id' => $companyArrByCode[$row['agent_code']]['id'],
                        'terminal' => ['ios' => 1, 'android' => 2][$row['terminal']],
                        'cost' => $row['cost'] * 100,
                        'expose' => $row['expose'],
                        'click' => $row['click'],
                        'download' => $row['download'],
                        'addtime' => $timestamp,
                    ]
                );
            }
        }

        $success = new MessageBag([
            'title' => '批量导入完成',
        ]);
        Log::debug('本次excel操作人', [
            'name' => Admin::user()->name
        ]);
        return back()->with(compact('success'));
    }


    public function del(Request $request, $idStr)
    {
        $rs = ServingDataService::delServing(explode(',', $idStr));
        if ($rs === true) {
            return response()->json([
                'status' => true,
                'message' => "删除成功",
            ]);
        } else {
            return response()->json([
                'status' => false,
                'message' => "删除失败," . $rs,
            ]);
        }
    }

}
